package core

import (
	"fmt"
	"time"

	"github.com/google/gopacket/pcap"
)

// SingleHandleManager 网络抓包请求配置
type SingleHandleManager struct {
	dev     string        // 网络设备名
	snaplen int32         // 数据包长度
	promisc bool          // 是否使用混杂模式
	timeout time.Duration // 超时时间
	filter  string        // BPF过滤器
	handle  *pcap.Handle  // 空的handle本身，方便设置和在类中传递
}

// NewCaptureRequest 构造器函数
// 参数说明：
//
//	dev - 必填，网络设备名
//	opts - 可选配置项（可变参数）
func NewSingleHandleManager(dev string, opts ...CaptureOption) (*SingleHandleManager, error) {
	// 初始化默认值
	req := &SingleHandleManager{
		dev:     dev,
		snaplen: 65535,       // 默认包长度
		promisc: true,        // 默认混杂模式
		timeout: time.Second, // 默认超时1秒
		filter:  "",          // 默认无过滤器
		handle:  nil,         // handle
	}

	// 应用可选配置
	for _, opt := range opts {
		opt(req)
	}

	init, err := req.Handle_Init()
	if err != nil {
		return req, fmt.Errorf("%s初始化handler失败", dev)
	}

	req.handle = init

	return req, nil
}

// CaptureOption 配置函数类型
type CaptureOption func(*SingleHandleManager)

// WithSnaplen 设置数据包长度
func WithSnaplen(length int32) CaptureOption {
	return func(req *SingleHandleManager) {
		req.snaplen = length
	}
}

// WithPromisc 设置混杂模式
func WithPromisc(promisc bool) CaptureOption {
	return func(req *SingleHandleManager) {
		req.promisc = promisc
	}
}

// WithTimeout 设置超时时间
func WithTimeout(timeout time.Duration) CaptureOption {
	return func(req *SingleHandleManager) {
		req.timeout = timeout
	}
}

// WithFilter 设置BPF过滤器
func WithFilter(filter string) CaptureOption {
	return func(req *SingleHandleManager) {
		req.filter = filter
	}
}

// 初始化好handle.
func (cr *SingleHandleManager) Handle_Init() (*pcap.Handle, error) {
	handle, err := pcap.OpenLive(
		cr.dev,
		cr.snaplen,
		cr.promisc,
		cr.timeout,
	)
	if err != nil {
		return nil, fmt.Errorf("打开设备失败: %w", err)
	}

	if cr.filter != "" {
		if err := handle.SetBPFFilter(cr.filter); err != nil {
			handle.Close()
			return nil, fmt.Errorf("设置过滤器失败: %w", err)
		}
	}

	return handle, nil
}

// String 打印配置信息
func (cr *SingleHandleManager) String() string {
	return fmt.Sprintf(
		"SingleHandleManager{dev: %q, snaplen: %d, promisc: %v, timeout: %v, filter: %q}",
		cr.dev, cr.snaplen, cr.promisc, cr.timeout, cr.filter,
	)
}

// 判断handle 存活, 这里使用双重检查锁判断
func (p *SingleHandleManager) IsHandleActive() bool {
	if p.handle == nil {
		return false
	}

	_, err := p.handle.Stats()
	return err == nil

}

// 关闭handleManager 如果有需要可以直接在这个函数里面扩充其他的结束函数
func (p *SingleHandleManager) Close() {
	p.handle.Close()
}
